/**
 * 八字算命服务
 * 提供八字排盘和分析功能
 */

const { logInfo, logError } = require('../logger');

// 定义天干
const TIANGAN = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];

// 定义地支
const DIZHI = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'];

// 定义生肖
const SHENGXIAO = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪'];

// 定义五行
const WUXING = ['木', '火', '土', '金', '水'];

// 天干五行属性
const TIANGAN_WUXING = {
  '甲': '木', '乙': '木',
  '丙': '火', '丁': '火',
  '戊': '土', '己': '土',
  '庚': '金', '辛': '金',
  '壬': '水', '癸': '水'
};

// 地支五行属性
const DIZHI_WUXING = {
  '寅': '木', '卯': '木',
  '巳': '火', '午': '火',
  '辰': '土', '戌': '土', '丑': '土', '未': '土',
  '申': '金', '酉': '金',
  '亥': '水', '子': '水'
};

// 地支藏干
const DIZHI_CANGAN = {
  '子': ['癸'],
  '丑': ['己', '癸', '辛'],
  '寅': ['甲', '丙', '戊'],
  '卯': ['乙'],
  '辰': ['戊', '癸', '乙'],
  '巳': ['丙', '庚', '戊'],
  '午': ['丁', '己'],
  '未': ['己', '丁', '乙'],
  '申': ['庚', '壬', '戊'],
  '酉': ['辛'],
  '戌': ['戊', '辛', '丁'],
  '亥': ['壬', '甲']
};

// 生肖对应的地支
const SHENGXIAO_DIZHI = {
  '鼠': '子', '牛': '丑', '虎': '寅', '兔': '卯',
  '龙': '辰', '蛇': '巳', '马': '午', '羊': '未',
  '猴': '申', '鸡': '酉', '狗': '戌', '猪': '亥'
};

// 时辰地支表（24小时制）
const SHICHEN_DIZHI = [
  { start: 23, end: 1, dizhi: '子' },   // 子时 23:00-1:00
  { start: 1, end: 3, dizhi: '丑' },    // 丑时 1:00-3:00
  { start: 3, end: 5, dizhi: '寅' },    // 寅时 3:00-5:00
  { start: 5, end: 7, dizhi: '卯' },    // 卯时 5:00-7:00
  { start: 7, end: 9, dizhi: '辰' },    // 辰时 7:00-9:00
  { start: 9, end: 11, dizhi: '巳' },   // 巳时 9:00-11:00
  { start: 11, end: 13, dizhi: '午' },  // 午时 11:00-13:00
  { start: 13, end: 15, dizhi: '未' },  // 未时 13:00-15:00
  { start: 15, end: 17, dizhi: '申' },  // 申时 15:00-17:00
  { start: 17, end: 19, dizhi: '酉' },  // 酉时 17:00-19:00
  { start: 19, end: 21, dizhi: '戌' },  // 戌时 19:00-21:00
  { start: 21, end: 23, dizhi: '亥' }   // 亥时 21:00-23:00
];

/**
 * 根据年份计算年柱天干地支
 * @param {number} year - 公历年份
 * @returns {Object} 年柱天干地支
 */
function calculateYearPillar(year) {
  // 1984年为甲子年（天干0，地支0）
  const baseYear = 1984;
  const yearDiff = year - baseYear;
  
  // 天干周期10年，地支周期12年
  const tianganIndex = (yearDiff + 10) % 10;
  const dizhiIndex = (yearDiff + 12) % 12;
  
  return {
    tiangan: TIANGAN[tianganIndex],
    dizhi: DIZHI[dizhiIndex]
  };
}

/**
 * 根据日期计算月柱天干地支（简化算法，实际需要查万年历）
 * @param {Date} date - 日期
 * @returns {Object} 月柱天干地支
 */
function calculateMonthPillar(date) {
  // 简化实现，实际需要查万年历
  // 这里使用一个近似算法
  const year = date.getFullYear();
  const month = date.getMonth() + 1;
  
  // 简化计算，实际应该查万年历
  // 这里使用固定的映射关系作为示例
  const monthMap = {
    1: { tiangan: '丙', dizhi: '寅' },
    2: { tiangan: '丁', dizhi: '卯' },
    3: { tiangan: '戊', dizhi: '辰' },
    4: { tiangan: '己', dizhi: '巳' },
    5: { tiangan: '庚', dizhi: '午' },
    6: { tiangan: '辛', dizhi: '未' },
    7: { tiangan: '壬', dizhi: '申' },
    8: { tiangan: '癸', dizhi: '酉' },
    9: { tiangan: '甲', dizhi: '戌' },
    10: { tiangan: '乙', dizhi: '亥' },
    11: { tiangan: '丙', dizhi: '子' },
    12: { tiangan: '丁', dizhi: '丑' }
  };
  
  return monthMap[month] || { tiangan: '丙', dizhi: '寅' };
}

/**
 * 根据日期计算日柱天干地支（简化算法，实际需要查万年历）
 * @param {Date} date - 日期
 * @returns {Object} 日柱天干地支
 */
function calculateDayPillar(date) {
  // 简化实现，实际需要查万年历
  // 这里使用一个固定的示例
  return {
    tiangan: '戊',
    dizhi: '午'
  };
}

/**
 * 根据小时计算时柱天干地支
 * @param {Date} date - 日期
 * @param {string} dayTiangan - 日柱天干
 * @returns {Object} 时柱天干地支
 */
function calculateHourPillar(date, dayTiangan) {
  const hour = date.getHours();
  
  // 确定时支
  let dizhi = '子';
  for (const shichen of SHICHEN_DIZHI) {
    if (shichen.start <= shichen.end) {
      // 不跨日的情况
      if (hour >= shichen.start && hour < shichen.end) {
        dizhi = shichen.dizhi;
        break;
      }
    } else {
      // 跨日的情况（子时）
      if (hour >= shichen.start || hour < shichen.end) {
        dizhi = shichen.dizhi;
        break;
      }
    }
  }
  
  // 确定时干（需要根据日干和时支推算）
  // 这里使用简化算法，实际应该查时辰天干表
  const hourTianganMap = {
    '甲': { '子': '甲', '丑': '乙', '寅': '丙', '卯': '丁', '辰': '戊', '巳': '己', '午': '庚', '未': '辛', '申': '壬', '酉': '癸', '戌': '甲', '亥': '乙' },
    '乙': { '子': '丙', '丑': '丁', '寅': '戊', '卯': '己', '辰': '庚', '巳': '辛', '午': '壬', '未': '癸', '申': '甲', '酉': '乙', '戌': '丙', '亥': '丁' },
    '丙': { '子': '戊', '丑': '己', '寅': '庚', '卯': '辛', '辰': '壬', '巳': '癸', '午': '甲', '未': '乙', '申': '丙', '酉': '丁', '戌': '戊', '亥': '己' },
    '丁': { '子': '庚', '丑': '辛', '寅': '壬', '卯': '癸', '辰': '甲', '巳': '乙', '午': '丙', '未': '丁', '申': '戊', '酉': '己', '戌': '庚', '亥': '辛' },
    '戊': { '子': '壬', '丑': '癸', '寅': '甲', '卯': '乙', '辰': '丙', '巳': '丁', '午': '戊', '未': '己', '申': '庚', '酉': '辛', '戌': '壬', '亥': '癸' },
    '己': { '子': '甲', '丑': '乙', '寅': '丙', '卯': '丁', '辰': '戊', '巳': '己', '午': '庚', '未': '辛', '申': '壬', '酉': '癸', '戌': '甲', '亥': '乙' },
    '庚': { '子': '丙', '丑': '丁', '寅': '戊', '卯': '己', '辰': '庚', '巳': '辛', '午': '壬', '未': '癸', '申': '甲', '酉': '乙', '戌': '丙', '亥': '丁' },
    '辛': { '子': '戊', '丑': '己', '寅': '庚', '卯': '辛', '辰': '壬', '巳': '癸', '午': '甲', '未': '乙', '申': '丙', '酉': '丁', '戌': '戊', '亥': '己' },
    '壬': { '子': '庚', '丑': '辛', '寅': '壬', '卯': '癸', '辰': '甲', '巳': '乙', '午': '丙', '未': '丁', '申': '戊', '酉': '己', '戌': '庚', '亥': '辛' },
    '癸': { '子': '壬', '丑': '癸', '寅': '甲', '卯': '乙', '辰': '丙', '巳': '丁', '午': '戊', '未': '己', '申': '庚', '酉': '辛', '戌': '壬', '亥': '癸' }
  };
  
  const tiangan = hourTianganMap[dayTiangan]?.[dizhi] || '甲';
  
  return {
    tiangan: tiangan,
    dizhi: dizhi
  };
}

/**
 * 八字排盘函数
 * @param {Date} birthDate - 出生日期时间
 * @returns {Object} 八字排盘结果
 */
function calculateBazi(birthDate) {
  try {
    // 记录日志
    logInfo('开始八字排盘计算', { birthDate: birthDate.toISOString() });
    
    // 计算四柱
    const yearPillar = calculateYearPillar(birthDate.getFullYear());
    const monthPillar = calculateMonthPillar(birthDate);
    const dayPillar = calculateDayPillar(birthDate);
    const hourPillar = calculateHourPillar(birthDate, dayPillar.tiangan);
    
    const bazi = {
      year: yearPillar,
      month: monthPillar,
      day: dayPillar,
      hour: hourPillar
    };
    
    // 记录日志
    logInfo('八字排盘计算完成');
    
    return bazi;
  } catch (error) {
    // 记录错误日志
    logError('八字排盘计算失败', { error: error.message });
    throw error;
  }
}

/**
 * 分析八字五行
 * @param {Object} bazi - 八字数据
 * @returns {Object} 五行分析结果
 */
function analyzeFiveElements(bazi) {
  const elements = {
    木: 0,
    火: 0,
    土: 0,
    金: 0,
    水: 0
  };
  
  // 统计天干五行
  ['year', 'month', 'day', 'hour'].forEach(pillar => {
    const tiangan = bazi[pillar].tiangan;
    const wuxing = TIANGAN_WUXING[tiangan];
    if (wuxing) {
      elements[wuxing]++;
    }
  });
  
  // 统计地支五行（考虑藏干）
  ['year', 'month', 'day', 'hour'].forEach(pillar => {
    const dizhi = bazi[pillar].dizhi;
    const cangan = DIZHI_CANGAN[dizhi] || [];
    cangan.forEach(gan => {
      const wuxing = TIANGAN_WUXING[gan];
      if (wuxing) {
        // 藏干权重较低，按0.5计算
        elements[wuxing] += 0.5;
      }
    });
    
    // 地支本气五行
    const dizhiWuxing = DIZHI_WUXING[dizhi];
    if (dizhiWuxing) {
      elements[dizhiWuxing]++;
    }
  });
  
  return elements;
}

/**
 * 八字分析函数
 * @param {Object} bazi - 八字数据
 * @returns {Object} 八字分析结果
 */
function analyzeBazi(bazi) {
  try {
    // 记录日志
    logInfo('开始八字分析');
    
    // 分析五行
    const fiveElements = analyzeFiveElements(bazi);
    
    // 简化的性格分析（实际应该更复杂）
    let personality = '';
    if (fiveElements.木 > 3) {
      personality = '此八字木旺，为人仁慈、有恻隐之心，性格温和，但有时过于固执。';
    } else if (fiveElements.火 > 3) {
      personality = '此八字火旺，为人热情、积极，有创造力，但有时容易急躁。';
    } else if (fiveElements.土 > 3) {
      personality = '此八字土旺，为人诚实、稳重，有包容心，但有时过于保守。';
    } else if (fiveElements.金 > 3) {
      personality = '此八字金旺，为人果断、正义，有决断力，但有时过于刚强。';
    } else if (fiveElements.水 > 3) {
      personality = '此八字水旺，为人聪明、灵活，有智慧，但有时过于多变。';
    } else {
      personality = '此八字五行较为均衡，为人聪明机智，做事有条不紊。';
    }
    
    // 简化的职业分析
    let career = '';
    if (fiveElements.木 > 2 && fiveElements.火 > 2) {
      career = '适合从事教育、文化、艺术类工作，有较强的表达能力。';
    } else if (fiveElements.土 > 2 && fiveElements.金 > 2) {
      career = '适合从事金融、管理、建筑类工作，有较强的组织能力。';
    } else if (fiveElements.水 > 2 && fiveElements.木 > 2) {
      career = '适合从事贸易、交通、物流类工作，有较强的沟通能力。';
    } else {
      career = '适合从事技术、研究类工作，有较强的专业能力。';
    }
    
    // 简化的关系分析
    let relationship = '';
    if (fiveElements.火 > 2 && fiveElements.土 > 2) {
      relationship = '感情较为顺利，但需注意沟通方式，避免冲突。';
    } else if (fiveElements.金 > 2 && fiveElements.水 > 2) {
      relationship = '感情较为复杂，需要更多的理解和包容。';
    } else {
      relationship = '感情较为稳定，但需注意平衡个人需求与伴侣需求。';
    }
    
    // 简化的健康分析
    let health = '';
    if (fiveElements.木 > 3) {
      health = '需注意肝胆方面的保养，保持情绪稳定。';
    } else if (fiveElements.火 > 3) {
      health = '需注意心脏和血液循环方面的保养，避免过度劳累。';
    } else if (fiveElements.土 > 3) {
      health = '需注意脾胃方面的保养，注意饮食规律。';
    } else if (fiveElements.金 > 3) {
      health = '需注意肺部和呼吸系统方面的保养，避免吸烟。';
    } else if (fiveElements.水 > 3) {
      health = '需注意肾脏和泌尿系统方面的保养，注意保暖。';
    } else {
      health = '身体健康状况良好，但需注意整体平衡。';
    }
    
    const analysis = {
      fiveElements: {
        wood: Math.round(fiveElements.木 * 100) / 100,
        fire: Math.round(fiveElements.火 * 100) / 100,
        earth: Math.round(fiveElements.土 * 100) / 100,
        metal: Math.round(fiveElements.金 * 100) / 100,
        water: Math.round(fiveElements.水 * 100) / 100
      },
      personality,
      career,
      relationship,
      health
    };
    
    // 记录日志
    logInfo('八字分析完成');
    
    return analysis;
  } catch (error) {
    // 记录错误日志
    logError('八字分析失败', { error: error.message });
    throw error;
  }
}

module.exports = {
  calculateBazi,
  analyzeBazi
};